package com.yupi.springbootinit.autocommit;

import cn.hutool.core.io.FileUtil;
import cn.hutool.extra.pinyin.PinyinUtil;
import com.yupi.springbootinit.model.dto.autoCommit.AutoCommitConst;
import com.yupi.springbootinit.utils.file.FileComparator;
import com.yupi.springbootinit.utils.file.FileCopy;
import com.yupi.springbootinit.utils.file.FileRead;
import com.yupi.springbootinit.utils.file.SmbFileRead;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.Nullable;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.stream.Collectors;

@Slf4j
@Component
public class AutoCommit {


    @Value("${weaver.module.location:module}")
    private String modulePathLogotype;

    @Resource
    private SmbFileRead smbFileRead;

    @PostConstruct
    private void initDir() {
        String modulePath = getModulePath(null, true);
        new File(modulePath).mkdirs();
        new File(modulePath,AutoCommitConst.CLIENT_PATH_DESCRIPTOR).mkdirs();
    }


    /**
     * 覆盖文件
     *
     * @param sourcePath      源文件夹根目录，结尾不能带路径分隔符
     * @param targetPath      目标文件夹根目录，结尾不能带路径分隔符
     * @param moduleFile      模版
     * @param iscover
     * @param isSMBFileSource
     * @return
     * @throws Exception
     */
    public FileActionResult copyAllFile(String sourcePath, String targetPath, String moduleFile, boolean iscover, boolean isSMBFileSource) throws Exception {
        FileActionResult fileActionResult = new FileActionResult();
        List<String> existFileList = new ArrayList<>();
        List<String> copyFileList = new ArrayList<>();
        fileActionResult.setRightFileList(copyFileList);
        fileActionResult.setLeftFileList(existFileList);
        List<String> moduleFileList = FileRead.readFile(moduleFile);
        return getFileActionResult(sourcePath, targetPath, moduleFileList, iscover, isSMBFileSource, fileActionResult, existFileList, copyFileList);
    }

    /**
     * 覆盖文件
     *
     * @param sourcePath      源文件夹根目录，结尾不能带路径分隔符
     * @param targetPath      目标文件夹根目录，结尾不能带路径分隔符
     * @param moduleFileList  需要拷贝文件列表
     * @param iscover
     * @param isSMBFileSource
     * @return
     * @throws Exception
     */
    public FileActionResult copyAllFile(String sourcePath, String targetPath, List<String> moduleFileList, boolean iscover, boolean isSMBFileSource) throws Exception {
        FileActionResult fileActionResult = new FileActionResult();
        List<String> existFileList = new ArrayList<>();
        List<String> copyFileList = new ArrayList<>();
        fileActionResult.setRightFileList(copyFileList);
        fileActionResult.setLeftFileList(existFileList);
        return getFileActionResult(sourcePath, targetPath, moduleFileList, iscover, isSMBFileSource, fileActionResult, existFileList, copyFileList);
    }

    private FileActionResult getFileActionResult(String sourcePath, String targetPath, List<String> moduleFileList, boolean iscover, boolean isSMBFileSource, FileActionResult fileActionResult, List<String> existFileList, List<String> copyFileList) {
        for (String moduleFileName : moduleFileList) {
            moduleFileName = formatFilePath(moduleFileName);
            boolean copyFlag = false;
            if (isSMBFileSource) {
                copyFlag = smbFileRead.copyFile(sourcePath + File.separator + moduleFileName, targetPath + File.separator + moduleFileName, iscover);
            } else {
                copyFlag = FileCopy.copyFile(sourcePath + File.separator + moduleFileName, targetPath + File.separator + moduleFileName, iscover);
            }
            if (copyFlag) {
                copyFileList.add(moduleFileName);
            } else {
                existFileList.add(moduleFileName);
            }
        }
        return fileActionResult;
    }


    @Nullable
    public FileActionResult sqlScriptInset(AutoCommitContext commitContext) {
        KBEnum kb = commitContext.getKb();
        FileActionResult fileActionResult = new FileActionResult();
        List<String> rightFileList = new ArrayList<>();
        List<String> leftFileList = new ArrayList<>();
        fileActionResult.setRightFileList(rightFileList);
        fileActionResult.setLeftFileList(leftFileList);
        if (kb != KBEnum.KB900231001) return fileActionResult;
        DbType dbType = commitContext.getDbType();
        String clientProjectPath = commitContext.getClientProjectPath();
        File sqlPath = new File(clientProjectPath + File.separator + AutoCommitConst.SQLUPGRADE);
        if (!sqlPath.exists()) {
            sqlPath.mkdirs();
        }
        String stencilPath = getStencilPath(commitContext, true);
        String targetPath = joinPath(clientProjectPath, AutoCommitConst.SQLUPGRADE, dbType.toString());
        String rawSqlFile = joinPath(stencilPath, AutoCommitConst.SQLUPGRADE, dbType.toString());
        File dir = new File(rawSqlFile);
        for (File sqlFile : dir.listFiles()) {
            String fileName = sqlFile.getName();
            String pinyin = PinyinUtil.getFirstLetter(commitContext.getClientName(), "");
            pinyin = pinyin.toUpperCase();
            File file = new File(joinPath(targetPath, fileName.replace(".sql", "") + pinyin + ".sql"));
            if (file.exists()) {
                leftFileList.add(file.getAbsolutePath().replace(clientProjectPath,""));
                continue;
            }
            boolean copyFlag = FileCopy.copyFile(joinPath(rawSqlFile, fileName), joinPath(targetPath, fileName), false);
            if (copyFlag) {
                File sqlfile = new File(joinPath(targetPath, fileName));
                File rename = FileUtil.rename(sqlfile, fileName.replace(".sql", "") + pinyin + ".sql", true);
                String relativePath = rename.getAbsolutePath().replace(clientProjectPath, "");
                rightFileList.add(relativePath);
                log.info("sql脚本覆盖及改名完成");
            }

        }
        return fileActionResult;
    }

    public String writeCopyFileList(AutoCommitContext commitContext,boolean rename) throws IOException {
        String modulePath = getModulePath(commitContext, true);
        List<String> neddFile = commitContext.getFileActionResult().getRightFileList();
        String clientName = commitContext.getClientName();
        String writeFileName = joinPath(modulePath, AutoCommitConst.CLIENT_PATH_DESCRIPTOR, clientName + ".txt");
        File file = new File(writeFileName);
        if (file.exists() && rename) {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yy_MM_dd_HH_mm_ss");
            String format = simpleDateFormat.format(new Date());
            FileUtil.rename(file, file.getName().replace(".txt", System.currentTimeMillis() + ".txt"), false);
            file.delete();
        }
        FileWriter fileWriter = new FileWriter(writeFileName, true);
        for (String nedd : neddFile) {
            fileWriter.write(nedd + "\n");
        }
        fileWriter.flush();

        log.info("写入客户已添加文件完成");
        return writeFileName;
    }

    /*public FileActionResult compareFileList(AutoCommitContext context, boolean needRemove) throws IOException {
        FileActionResult fileActionResult = new FileActionResult();
        List<String> noEqFileList = new ArrayList<>();
        List<String> eqFileList = new ArrayList<>();
        fileActionResult.setRightFileList(eqFileList);
        fileActionResult.setLeftFileList(noEqFileList);
        List<String> copyFileList = context.getFileActionResult().getRightFileList();
        String initStencilPath = getInitStencilPath(context, true);
        String clientProjectPath = context.getClientProjectPath();

        for (String path : copyFileList) {
            boolean ifEquals = FileComparator.areFilesEqual(initStencilPath + File.separator + path, clientProjectPath + File.separator + path);
            if (ifEquals) {
                eqFileList.add(path);
            } else {
                noEqFileList.add(path);
                if (needRemove) {
                    new File(clientProjectPath + File.separator + path).delete();
                }
            }

        }
        log.info("文件对比完成:{}", fileActionResult);
        return fileActionResult;
    }*/

    /**
     * 与模版库比较
     * @param sourcePro
     * @param targetPro
     * @param compareFileList
     * @param needRemove
     * @return
     * @throws IOException
     */
    public FileActionResult compareFileList(String sourcePro,String targetPro,List<String> compareFileList, boolean needRemove) throws IOException {
        FileActionResult fileActionResult = new FileActionResult();
        List<String> noEqFileList = new ArrayList<>();
        List<String> eqFileList = new ArrayList<>();
        fileActionResult.setRightFileList(eqFileList);
        fileActionResult.setLeftFileList(noEqFileList);

        for (String path : compareFileList) {
            boolean ifEquals = FileComparator.areFilesEqual(sourcePro + path, targetPro + path);
            if (ifEquals) {
                eqFileList.add(path);
            } else {
                noEqFileList.add(path);
                if (needRemove) {
                    new File(targetPro + File.separator + path).delete();
                }
            }

        }
        log.info("文件对比完成:{}", fileActionResult);
        return fileActionResult;
    }

    /**
     * 生成文件根目录
     *
     * @param commitContext
     * @param isAbsPath     是否需要绝对路径
     * @return
     */
    public String getModulePath(AutoCommitContext commitContext, boolean isAbsPath) {
        return (isAbsPath ? System.getProperty("user.dir") + File.separator : "") + modulePathLogotype;
    }

    /**
     * 组合当前kb需要覆盖的文件列表文件目录
     *
     * @param commitContext
     * @param isAbsPath     是否需要绝对路径
     * @return
     */
    public String getStencilPath(AutoCommitContext commitContext, boolean isAbsPath) {
        return getModulePath(commitContext, true) + File.separator + "模板库";
    }

    /**
     * 组合当前kb需要覆盖的文件列表文件目录
     *
     * @param commitContext
     * @param isAbsPath     是否需要绝对路径
     * @return
     */
    public String getInitStencilPath(AutoCommitContext commitContext, boolean isAbsPath) {
        KBEnum kb = commitContext.getKb();
        String kbModule = "2310原始模板库";

        if (kb.getKbNumber()>5) {
            kbModule = "2401原始模板库";
        }
        return joinPath(getModulePath(commitContext, true), kbModule);
    }

    /**
     * 获取： 组合当前kb需要覆盖的文件列表 的文件目录
     *
     * @param commitContext
     * @param isAbsPath     是否需要绝对路径
     * @return
     */
    @Deprecated
    public String getNeedCommitFileListFileName(AutoCommitContext commitContext, boolean isAbsPath) {
        return joinPath(getModulePath(commitContext, true), commitContext.getKb().getSourceFileListFileName());
    }


    public static String formatFilePath(String rawFileName) {
        String separator = File.separator;
        return rawFileName.replaceAll("\\\\",  Matcher.quoteReplacement(File.separator)).replaceAll("/", Matcher.quoteReplacement(File.separator));
    }

    public String joinPath(String... names) {
        return Arrays.stream(names).collect(Collectors.joining(File.separator));

    }

    @Data
    public class FileActionResult {
        List<String> leftFileList;
        List<String> rightFileList;
    }
}
